import { Inject } from '@nestjs/common';
import {
  WebSocketGateway,
  WebSocketServer,
  SubscribeMessage,
  OnGatewayInit,
  OnGatewayConnection,
  OnGatewayDisconnect,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { MatchService } from 'src/modules/match/match.service';
import { MatchServiceV2 } from 'src/modules/match/match.service.v2';
import { MatchStatusEnum } from 'src/common/constant/enums';
import { WsSubscribeMsg, WsEmitMsg } from './constant/constant';
import logger from 'src/common/utils/log';

@WebSocketGateway({
  cors: {
    origin: '*',
  },
})
export class WebsocketsServer
  implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
  constructor(
    @Inject(MatchService) private readonly matchService: MatchService,
    @Inject(MatchServiceV2) private readonly MatchServiceV2: MatchServiceV2,
  ) {}

  @WebSocketServer() server: Server;

  afterInit(server: Server) {
    logger.info('WebSocket server initialized');
  }

  handleConnection(client: Socket, ...args: any[]) {
    try {
      const tournamentId = client.handshake.query.tournamentId as string;
      if (tournamentId) {
        // 客户端连接时加入对应的房间
        client.join(`tournament_${tournamentId}`);
        logger.info(
          `Client ${client.id} joined room tournament_${tournamentId}`,
        );
      }
      logger.info(`Client connected: ${client.id}`);
    } catch (e) {
      logger.error(e);
    }
  }

  handleDisconnect(client: Socket) {
    const tournamentId = client.handshake.query.tournamentId as string;
    if (tournamentId) {
      // 客户端断开连接时离开对应的房间
      client.leave(`tournament_${tournamentId}`);
      logger.info(`Client ${client.id} left room tournament_${tournamentId}`);
    }
    logger.info(`Client disconnected: ${client.id}`);
  }

  @SubscribeMessage(WsSubscribeMsg.GET_PLAYING_MATCHES)
  async handleMessage(client: Socket, payload: { tournamentId: number }) {
    logger.info(`start getPlayingMatches ${JSON.stringify(payload)}`);
    const { tournamentId } = payload;
    const matches = await this.matchService.getInProgressMatches(
      tournamentId,
      // MatchStatusEnum.InProgress,
    );
    // 只向对应的房间广播消息
    this.server
      .to(`tournament_${tournamentId}`)
      .emit(WsEmitMsg.UPDATE_PLAYING_MATCH, matches);
  }

  @SubscribeMessage(WsSubscribeMsg.GET_PLAYING_MATCHES_V2)
  async getPlayingMatchesV2(client: Socket, payload: { tournamentId: number }) {
    logger.info(`start getPlayingMatchesV2 ${JSON.stringify(payload)}`);
    const { tournamentId } = payload;
    const matches = await this.MatchServiceV2.getInProgressMatches(
      tournamentId,
      // MatchStatusEnum.InProgress,
    );
    // 只向对应的房间广播消息
    this.server
      .to(`tournament_${tournamentId}`)
      .emit(WsEmitMsg.UPDATE_PLAYING_MATCH_V2, matches);
  }
}
